package com.fingard.dsp.bank.directbank.fubon01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.MFSHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.ForeignBankUtil;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.sql.Connection;
import java.util.*;


public class FUBON01BatPayRec extends FUBON01Base implements IBatPayRec {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,REQSEQID,BANKREQSEQID,RESERVE1) values (?,?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT RESERVE1 FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";

    private static final String INTERNEXTID = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,RESERVE1) values(?,?,?,?);";
    private static final String SELECTNEXTID = "SELECT RESERVE1 FROM REQSEQIDMAPPING WHERE BANKCODE=? and TRANSDATE=?;";
    private static final String UPDATENEXTID = "UPDATE REQSEQIDMAPPING SET RESERVE1=? WHERE BANKCODE=? and TRANSDATE=?;";

    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        XmlTextWriter xmlWriter = new XmlTextWriter();//发送给银行的报文
        Connection conn = FGBiz.getLocalDbConn();
        String transDate = p_req1988.reqHeader.transTime.substring(0, 10).replaceAll("-", "");
        String nextIDStr = "0001";
        Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTNEXTID, new Object[]{p_req1988.reqHeader.bankCode, transDate});
        if (map.size() == 0) {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            JDBCHelper.update(conn, INTERNEXTID, new Object[]{uuid, p_req1988.reqHeader.bankCode, transDate, nextIDStr});
        } else {
            nextIDStr = String.format("%04d", Integer.parseInt(map.get("RESERVE1").toString()) + 1);
            JDBCHelper.update(conn, UPDATENEXTID, new Object[]{nextIDStr, p_req1988.reqHeader.bankCode, transDate});
        }
        String p_FileName = "TMS_" + p_req1988.reqHeader.transTime.substring(0, 10).replaceAll("-", "") + "_" + nextIDStr;

        Map<String, Object> resultAndfileContext = new HashMap<String, Object>();
        resultAndfileContext = writerPayFileContext(p_req1988);//文件内容拼接
        SftpPortClient sftpPortClient = null;
        try {
            WriteBankLogLn("开始上传文件至SFTP...");
            String payFullFileName = getBankConfig().getValueAsString("PayFilePath") + File.separator + p_FileName + ".txt";
            WriteBankLogLn("本地SFTP支付映射文件存放目录：" + payFullFileName);
            //写入支付文件内容到本地
            if (!exportContentToFile(resultAndfileContext.get("fileContext").toString(), payFullFileName)) {
                retAts.respCode = "-1";
                retAts.respInfo = "生成本地支付文件失败！";
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.writeRetToATS();
                return retAts;
            }
            //上传付款文件到SFTP
            FtpSet ftpSet = bankFront.getFtpSet("sftpserver");
            sftpPortClient = new SftpPortClient(ftpSet);
            FtpReceiver ftpReceiver1 = null;
            ftpReceiver1 = sftpPortClient.uploadFile("", payFullFileName, p_FileName + ".txt");
            //付款文件不加密
            if (ftpReceiver1.isCompleted) {
                WriteBankLogLn("支付文件上传SFTP成功");
                //上传成功后，银行提供接口要求上传XXX.ok确认文件文件内容为空
                String payFullFileNameOk = getBankConfig().getValueAsString("PayFilePath") + File.separator + p_FileName + ".ok";
                //.ok确认文件写入本地
                FileHelper.writeFile(payFullFileNameOk, "", "UTF-8");
                WriteBankLogLn2("写入文件：" + payFullFileNameOk);
                FtpReceiver ftpReceiver2 = null;
                ftpReceiver2 = sftpPortClient.uploadFile("", payFullFileNameOk, p_FileName + ".ok");
                if (ftpReceiver2.isCompleted) {
                    WriteBankLogLn("支付确认文件上传SFTP成功");
                } else {
                    WriteBankLogLn("支付确认文件上传SFTP失败");
                    retAts.respCode = "-1";
                    retAts.respInfo = "支付确认文件上传SFTP失败";
                    retAts.writeRetToATS();
                    return retAts;
                }
            } else {
                WriteBankLogLn("支付文件上传SFTP失败");
                retAts.respCode = "-1";
                retAts.respInfo = "支付文件上传SFTP失败";
                retAts.writeRetToATS();
                return retAts;
            }
            //上传SFTP目录成功后，将本地文件名(含路径)以及批次号存入，待查询批次交易结果时使用
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{uuid, p_req1988.reqHeader.bankCode, p_req1988.reqBatchNO, p_req1988.reqBatchNO, payFullFileName});

            //全局流水号
            String transSeqId = p_req1988.reqHeader.transSeqID;
            transSeqId = bankFront.corpNo + "01" + "302020" + Format.Date8Format.format(new Date()) + "00" + transSeqId.substring(transSeqId.length() - 8, transSeqId.length());

            FUBON01Header fubon01Header = new FUBON01Header();
            fubon01Header.ServiceCode = "06001030001";//服务唯一标识，由EAI提供
            fubon01Header.ServiceScene = "01";//服务场景
            fubon01Header.InitiatorId = "203010";//发起方系统编号
            fubon01Header.ServiceId = "302020";//服务系统编号
            fubon01Header.TranDate = Format.Date8Format.format(new Date());//前台交易日期 YYYYMMDD
            fubon01Header.TranTime = Format.Time6Format.format(new Date());//前台交易时间 hhmmss
            fubon01Header.OrgConSeqNo = transSeqId;//发起方流水号 全局流水号
            fubon01Header.ConsumerSeqNo = transSeqId;//消费方流水号 调用方产生流水号
            fubon01Header.FileFlag = "1";//文件标识 1-有文件，0-无文件
            writeCommonHeader(xmlWriter, fubon01Header);

            xmlWriter.writeStartElement("Body");
            xmlWriter.writeElementString("BatchFile", p_FileName + ".txt");//批量文件名称
            xmlWriter.writeElementString("BatchNo", p_req1988.reqBatchNO);//批次号
            xmlWriter.writeElementString("TerminalId", "");//终端号
            xmlWriter.writeElementString("PgupOrPgdn", "");//上翻/下翻标志 取值范围：0- 上翻 1- 下翻 默认0
            xmlWriter.writeElementString("TotalNum", "");//本页记录总数
            xmlWriter.writeElementString("CurrentNum", "");//当前记录号
            xmlWriter.writeElementString("PageStart", "");//本页第一笔标志
            xmlWriter.writeElementString("PageEnd", "");//本页最后一笔标志
            xmlWriter.writeElementString("TotalRows", "");//总笔数
            xmlWriter.writeElementString("TotalPages", "");//总页数
            xmlWriter.writeElementString("TotalFlag", "");//汇总标志 取值范围：N-不查询总笔数总页数 E-指定总笔数计算查询页数 O-动态计算查询结果页数 默认为N
            xmlWriter.writeEndDocument();

            //gxp通讯报文头
            fubon01Header.glbTrSeq = transSeqId;
            fubon01Header.recvId = "UPPF";//服务方ID
            String gxpHeader = writeGxpHeader(fubon01Header, xmlWriter.toXmlString());

            String[] tmpStrRet = sendToBankPay(gxpHeader, gxpHeader + xmlWriter.toXmlString());// 发送银行
//            String[] tmpStrRet = {"", "<ATSYH>\n" +
//                    "  <TransResp>\n" +
//                    "    <BankCode>FUBON01</BankCode>\n" +
//                    "    <TransType>1988</TransType>\n" +
//                    "    <TransSeqID>20200306130524106</TransSeqID>\n" +
//                    "    <TransParam>\n" +
//                    "      <DetailRecord>\n" +
//                    "        <NewReqSeqID />\n" +
//                    "        <RespCode>0</RespCode>\n" +
//                    "        <RespInfo>交易成功</RespInfo>\n" +
//                    "        <TransState>000000</TransState>\n" +
//                    "        <ReqSeqID>306130524106</ReqSeqID>\n" +
//                    "        <PayInfoCode>000000</PayInfoCode>\n" +
//                    "      </DetailRecord>\n" +
//                    "    </TransParam>\n" +
//                    "  </TransResp>\n" +
//                    "</ATSYH>"};
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/service/GapsAppHead/RespCode");
                    String returnMsg = tmpBkReader.getFirstText("/service/GapsAppHead/RespMsg");
                    //该交易采用异步处理，银行先接受交易，返回企业交易受理成功，转账结果，由企业来查询交易处理结果。
                    retAts.respCode = "0";
                    retAts.respInfo = returnMsg;
                    retAts.reqSeqID = p_req1988.reqBatchNO;
                    retAts.transState = returnCode;
                    retAts.payInfoCode = retAts.transState;
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = "批量转账出现异常！";
            WriteBankLogLn("批量转账出现异常,异常信息：" + e.getMessage());
        } finally {
            conn.close();
        }
        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        Connection conn = FGBiz.getLocalDbConn();
        SftpPortClient sftpPortClient = null;
        try {
            //全局流水号
            String transSeqId = p_req1998.reqHeader.transSeqID;
            transSeqId = bankFront.corpNo + "01" + "302020" + Format.Date8Format.format(new Date()) + "00" + transSeqId.substring(transSeqId.length() - 8, transSeqId.length());

            XmlTextWriter xmlWriter = new XmlTextWriter();//发送给银行的报文
            FUBON01Header fubon01Header = new FUBON01Header();
            fubon01Header.ServiceCode = "06002030001";//服务唯一标识，由EAI提供
            fubon01Header.ServiceScene = "01";//服务场景
            fubon01Header.InitiatorId = "203010";//发起方系统编号
            fubon01Header.ServiceId = "302020";//服务系统编号
            fubon01Header.TranDate = Format.Date8Format.format(new Date());//前台交易日期 YYYYMMDD
            fubon01Header.TranTime = Format.Time6Format.format(new Date());//前台交易时间 hhmmss
            fubon01Header.OrgConSeqNo = transSeqId;//发起方流水号 全局流水号
            fubon01Header.ConsumerSeqNo = transSeqId;//消费方流水号 调用方产生流水号
            fubon01Header.FileFlag = "1";//文件标识 1-有文件，0-无文件
            writeCommonHeader(xmlWriter, fubon01Header);

            xmlWriter.writeStartElement("Body");
            xmlWriter.writeElementString("BatchNo", p_req1998.reqBatchNO);//批次号
            xmlWriter.writeElementString("TerminalId", "");//终端号
            xmlWriter.writeElementString("PgupOrPgdn", "");//上翻/下翻标志 取值范围：0- 上翻 1- 下翻 默认0
            xmlWriter.writeElementString("TotalNum", "");//本页记录总数
            xmlWriter.writeElementString("CurrentNum", "");//当前记录号
            xmlWriter.writeElementString("PageStart", "");//本页第一笔标志
            xmlWriter.writeElementString("PageEnd", "");//本页最后一笔标志
            xmlWriter.writeElementString("TotalRows", "");//总笔数
            xmlWriter.writeElementString("TotalPages", "");//总页数
            xmlWriter.writeElementString("TotalFlag", "");//汇总标志 取值范围：N-不查询总笔数总页数 E-指定总笔数计算查询页数 O-动态计算查询结果页数 默认为N
            xmlWriter.writeEndDocument();

            //gxp通讯报文头
            fubon01Header.glbTrSeq = transSeqId;
            fubon01Header.recvId = "UPPF";//服务方ID
            String gxpHeader = writeGxpHeader(fubon01Header, xmlWriter.toXmlString());

            String[] tmpStrRet = sendToBankPay(gxpHeader, gxpHeader + xmlWriter.toXmlString());// 发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/service/GapsAppHead/RespCode");
                    String returnMsg = tmpBkReader.getFirstText("/service/GapsAppHead/RespMsg");
                    if (returnCode.equals("000000")) {
                        String returnFileName = tmpBkReader.getFirstText("/service/Body/ResultFile");//包含路径

                        if (StringHelper.isNullOrEmpty(returnFileName)) {
                            retAts.respCode = "-1";
                            retAts.respInfo = "银行返回未返回批量结果文件名！";
                            retAts.writeAfterDetail();
                            return retAts;
                        } else {
                            //本地发起交易的批量文件
                            Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1998.reqBatchNO, p_req1998.reqHeader.bankCode});
                            if (map.size() == 0) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "数据库没有该批次映射记录";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                            String tmpLocalBatchFileName = map.get("RESERVE1").toString();
                            WriteBankLogLn2("批次本地流水映射文件路径: " + tmpLocalBatchFileName);
                            File localMarkFile = new File(tmpLocalBatchFileName);
                            if (!localMarkFile.exists()) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "批次本地流水映射文件未生成,未发生交易!";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                            String tmpSeqIDData = FileHelper.readToString(localMarkFile, "UTF-8");
                            WriteBankLogLn2("本地流水映射文件内容:" + tmpSeqIDData);
                            if (StringHelper.isNullOrEmpty(tmpSeqIDData)) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "批次本地流水映射文件内容为空,未发生交易!";
                                retAts.writeAfterDetail();
                                return retAts;
                            }

                            String tmpResultData = null;//读取SFTP服务器的银行返回文件数据
                            String receivePath = StringHelper.trimEndFileSp(getBankConfig().getValueAsString("ReceiveFilePath")) + File.separator;//本地存储下载文件的目录
                            if (!FileHelper.existFile(receivePath)) {
                                FileHelper.mkdir(receivePath);
                            }
                            // sftp下载文件
                            FtpSet ftpSet = bankFront.getFtpSet("sftpserver");
                            sftpPortClient = new SftpPortClient(ftpSet);
                            FtpReceiver ftpReceiver = null;
                            returnFileName = returnFileName.substring(returnFileName.lastIndexOf("/") + 1, returnFileName.length());
                            String sftpDownloadFullFileName = receivePath + returnFileName;
                            ftpReceiver = sftpPortClient.downloadFile("", returnFileName, sftpDownloadFullFileName);
                            if (!ftpReceiver.isCompleted) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "Sftp下载" + returnFileName + "失败";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                            File sftpDownloadFile = new File(sftpDownloadFullFileName);
                            if (!sftpDownloadFile.exists()) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "本地未找到SFTP下载的文件(" + returnFileName + ")";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                            //获取sftp下载到本地的银行返回结果文件内容
                            tmpResultData = FileHelper.readToString(sftpDownloadFile, "UTF-8");
                            if (tmpResultData == null) {
                                this.WriteBankLogLn("读取前置数据文件返回为null，需确认前置文件夹配置和文件是否存在");
                            } else {
                                this.WriteBankLogStep3(tmpResultData);
                            }
                            StringBuilder tmpSbLog = new StringBuilder();
                            //处理数据内容
                            ArrayList<String[]> tmpArrayList = MFSHelper.getTextArray(tmpResultData, "|", 20, -1, tmpSbLog);
                            if (Integer.parseInt(p_req1998.totalNum) != tmpArrayList.size()) {
                                retAts.respCode = "-1";
                                retAts.respInfo = "该请求查询批次的总笔数与银行返回结果文件数据的交易笔数不相等！";
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                            if (tmpSbLog.length() == 0) {
                                retAts.reqSeqID = p_req1998.reqHeader.reqSeqID;
                                retAts.respCode = "0";
                                retAts.respInfo = "查询批量支付状态操作成功！";
                                for (int i = 0; i < tmpArrayList.size(); i++) {
                                    String[] tmpEachArr = tmpArrayList.get(i);
                                    //0交易流水|1付款账号|2付款人名称|3绑定账号|4有效证件种类|5有效证件种号|6收款账号|7收款人名称|8币种|9交易金额|10转账类型|11收款行行号|12支付状态|13附言|
                                    //14处理结果|15报错代码|16报错说明|17核心交易流水号/核心业务编号 |18电子账号客户名称|19交易后电子账户余额|
                                    //1、处理状态 0-未处理、1-成功，2-其他错误，错误信息在附言中
                                    //2、支付状态 0：成功  1：失败  2：处理中  3：已退汇  4：已冲正
                                    RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                    tmpRetDetail.postScript = tmpEachArr[0].trim().substring(14);//批次内每一笔的流水号(支付时会加上日期YYYYMMDDhhmmss)
                                    tmpRetDetail.payAct = p_req1998.ownAct;//付方账号
                                    tmpRetDetail.recAct = tmpEachArr[6];//收方账号
                                    tmpRetDetail.recName = tmpEachArr[7];//收方户名
                                    tmpRetDetail.curType = getBankConfig().getMapValueByKey("currencyMapping2", tmpEachArr[8]);//币种
                                    tmpRetDetail.payAmount = tmpEachArr[9];//交易金额
                                    if (tmpEachArr[14].equals("0")) {//未处理
                                        tmpRetDetail.result = tmpEachArr[14];
                                    } else if (tmpEachArr[14].equals("1")) {//处理成功
                                        tmpRetDetail.result = tmpEachArr[14] + "+" + tmpEachArr[12];
                                    } else {
                                        //出错
                                        tmpRetDetail.result = tmpEachArr[14] + "+" + tmpEachArr[15];
                                    }
                                    tmpRetDetail.payInfoCode = tmpRetDetail.result;
                                    tmpRetDetail.memo = tmpEachArr[16];
                                    tmpRetDetail.usage = tmpEachArr[13];//用途
                                    retAts.writeRetDetail(tmpRetDetail);
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = tmpSbLog.toString();
                                retAts.writeAfterDetail();
                                return retAts;
                            }
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = returnMsg;
                        retAts.writeAfterDetail();
                        return retAts;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                    retAts.writeAfterDetail();
                    return retAts;
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
                retAts.writeAfterDetail();
                return retAts;
            }
        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = "批量交易结果查询出现异常！";
            WriteBankLogLn("批量交易结果查询出现异常,异常信息：" + e.getMessage());
            e.printStackTrace();
            retAts.writeAfterDetail();
            return retAts;
        } finally {
            conn.close();
        }
        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return null;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return null;
    }
}
